using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Threading;
using System.IO;

using SLProxy;
using libsecondlife;
using libsecondlife.Packets;
using System.Net;
using System.Web.UI.HtmlControls;

namespace StickyChat
{
    public class StickyTranslate : UserControl, StickIn
    {
        private StickyServices loader;
        private string myName;
        private ComboBox OutTo;
        private CheckBox translateOutgoing;
        private Label OutToLabel;
        private Label PoweredByGoogle;
        private ComboBox InTo;
        private CheckBox translateIncoming;
        private Label InToLabel;
        private ComboBox InFrom;
        private ComboBox OutFrom;

        public StickyTranslate(StickyServices p)
        {
            loader = p;
            myName = "Translate";
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            this.OutTo = new System.Windows.Forms.ComboBox();
            this.translateOutgoing = new System.Windows.Forms.CheckBox();
            this.OutToLabel = new System.Windows.Forms.Label();
            this.OutFrom = new System.Windows.Forms.ComboBox();
            this.PoweredByGoogle = new System.Windows.Forms.Label();
            this.InTo = new System.Windows.Forms.ComboBox();
            this.translateIncoming = new System.Windows.Forms.CheckBox();
            this.InToLabel = new System.Windows.Forms.Label();
            this.InFrom = new System.Windows.Forms.ComboBox();
            this.SuspendLayout();
            // 
            // OutTo
            // 
            this.OutTo.FormattingEnabled = true;
            this.OutTo.Items.AddRange(new object[] {
            "English",
            "French",
            "German",
            "Italian",
            "Portuguese",
            "Spanish"});
            this.OutTo.Location = new System.Drawing.Point(168, 23);
            this.OutTo.Name = "OutTo";
            this.OutTo.Size = new System.Drawing.Size(121, 21);
            this.OutTo.TabIndex = 7;
            this.OutTo.Text = "English";
            // 
            // translateOutgoing
            // 
            this.translateOutgoing.AutoSize = true;
            this.translateOutgoing.Location = new System.Drawing.Point(3, 3);
            this.translateOutgoing.Name = "translateOutgoing";
            this.translateOutgoing.Size = new System.Drawing.Size(150, 17);
            this.translateOutgoing.TabIndex = 6;
            this.translateOutgoing.Text = "Translate my outgoing text";
            this.translateOutgoing.UseVisualStyleBackColor = true;
            // 
            // OutToLabel
            // 
            this.OutToLabel.AutoSize = true;
            this.OutToLabel.Location = new System.Drawing.Point(132, 26);
            this.OutToLabel.Name = "OutToLabel";
            this.OutToLabel.Size = new System.Drawing.Size(30, 13);
            this.OutToLabel.TabIndex = 5;
            this.OutToLabel.Text = "~to~";
            // 
            // OutFrom
            // 
            this.OutFrom.FormattingEnabled = true;
            this.OutFrom.Items.AddRange(new object[] {
            "English",
            "French",
            "German",
            "Italian",
            "Portuguese",
            "Spanish"});
            this.OutFrom.Location = new System.Drawing.Point(3, 23);
            this.OutFrom.Name = "OutFrom";
            this.OutFrom.Size = new System.Drawing.Size(123, 21);
            this.OutFrom.TabIndex = 4;
            this.OutFrom.Text = "English";
            // 
            // PoweredByGoogle
            // 
            this.PoweredByGoogle.AutoSize = true;
            this.PoweredByGoogle.Location = new System.Drawing.Point(3, 95);
            this.PoweredByGoogle.Name = "PoweredByGoogle";
            this.PoweredByGoogle.Size = new System.Drawing.Size(175, 13);
            this.PoweredByGoogle.TabIndex = 8;
            this.PoweredByGoogle.Text = "*Relies upon Google for translations";
            // 
            // InTo
            // 
            this.InTo.FormattingEnabled = true;
            this.InTo.Items.AddRange(new object[] {
            "English",
            "French",
            "German",
            "Italian",
            "Portuguese",
            "Spanish"});
            this.InTo.Location = new System.Drawing.Point(169, 70);
            this.InTo.Name = "InTo";
            this.InTo.Size = new System.Drawing.Size(121, 21);
            this.InTo.TabIndex = 12;
            this.InTo.Text = "English";
            // 
            // translateIncoming
            // 
            this.translateIncoming.AutoSize = true;
            this.translateIncoming.Location = new System.Drawing.Point(4, 50);
            this.translateIncoming.Name = "translateIncoming";
            this.translateIncoming.Size = new System.Drawing.Size(135, 17);
            this.translateIncoming.TabIndex = 11;
            this.translateIncoming.Text = "Translate incoming text";
            this.translateIncoming.UseVisualStyleBackColor = true;
            // 
            // InToLabel
            // 
            this.InToLabel.AutoSize = true;
            this.InToLabel.Location = new System.Drawing.Point(133, 73);
            this.InToLabel.Name = "InToLabel";
            this.InToLabel.Size = new System.Drawing.Size(30, 13);
            this.InToLabel.TabIndex = 10;
            this.InToLabel.Text = "~to~";
            // 
            // InFrom
            // 
            this.InFrom.FormattingEnabled = true;
            this.InFrom.Items.AddRange(new object[] {
            "English",
            "French",
            "German",
            "Italian",
            "Portuguese",
            "Spanish"});
            this.InFrom.Location = new System.Drawing.Point(4, 70);
            this.InFrom.Name = "InFrom";
            this.InFrom.Size = new System.Drawing.Size(123, 21);
            this.InFrom.TabIndex = 9;
            this.InFrom.Text = "English";
            // 
            // StickyTranslate
            // 
            this.Controls.Add(this.InTo);
            this.Controls.Add(this.translateIncoming);
            this.Controls.Add(this.InToLabel);
            this.Controls.Add(this.InFrom);
            this.Controls.Add(this.PoweredByGoogle);
            this.Controls.Add(this.OutTo);
            this.Controls.Add(this.translateOutgoing);
            this.Controls.Add(this.OutToLabel);
            this.Controls.Add(this.OutFrom);
            this.Name = "StickyTranslate";
            this.Size = new System.Drawing.Size(295, 114);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #region StickIn Members

        public string name
        {
            get { return myName; }
        }

        public void start()
        {
            loader.proxy.AddDelegate(PacketType.ChatFromViewer, Direction.Outgoing, new PacketDelegate(ChatFromViewer));
            loader.proxy.AddDelegate(PacketType.ChatFromSimulator, Direction.Incoming, new PacketDelegate(ChatFromSimulator));
        }

        public void stop()
        {
            loader.proxy.RemoveDelegate(PacketType.ChatFromViewer, Direction.Outgoing, new PacketDelegate(ChatFromViewer));
            loader.proxy.RemoveDelegate(PacketType.ChatFromSimulator, Direction.Incoming, new PacketDelegate(ChatFromSimulator));
        }
        #endregion StickIn Members

        private Packet ChatFromViewer(Packet packet, IPEndPoint sim)
        {
            // delegate the work as soon as possible
            ChatFromViewerPacket chat = (ChatFromViewerPacket)packet;
            if (this.translateOutgoing.Checked && chat.ChatData.Type<3 && chat.ChatData.Channel==0 && chat.ChatData.Length>2)
            {
                ThreadStart job = delegate { translateOut(loader.proxy, chat, OutFrom.Text, OutTo.Text); };
                (new Thread(job)).Start();
            }

            // return packet unmodified
            return packet;
        }

        private Packet ChatFromSimulator(Packet packet, IPEndPoint sim)
        {
            // delegate the work as soon as possible
            ChatFromSimulatorPacket chat = (ChatFromSimulatorPacket)packet;
            if (this.translateIncoming.Checked && chat.ChatData.Audible!=0 && chat.ChatData.ChatType < 3 && chat.ChatData.Length > 2)
            {
                ThreadStart job = delegate { translateIn(loader.proxy, chat, InFrom.Text, InTo.Text); };
                (new Thread(job)).Start();
            }

            // return packet unmodified
            return packet;
        }

        private string GetLangAbbreviation(string lang)
        {
            if (lang == "English")
            {
                return "en";
            }
            else if (lang == "French")
            {
                return "fr";
            }
            else if (lang == "German")
            {
                return "de";
            }
            else if (lang == "Italian")
            {
                return "it";
            }
            else if (lang == "Portuguese")
            {
                return "pt";
            }
            else if (lang == "Spanish")
            {
                return "es";
            }
            else
            {
                return "en";
            }
        }

        private void translateIn(Proxy p, ChatFromSimulatorPacket chat, string from, string to)
        {
            string result = translate(Helpers.FieldToUTF8String(chat.ChatData.Message),from,to);
            if (result != null)
            {
                chat.ChatData.Message = Helpers.StringToField(result);
                loader.proxy.InjectPacket(chat, Direction.Incoming);
            }
        }

        private void translateOut(Proxy p, ChatFromViewerPacket chat, string from, string to)
        {
            string result = translate(Helpers.FieldToUTF8String(chat.ChatData.Message),from,to);
            if (result != null)
            {
                chat.ChatData.Message = Helpers.StringToField(result);
                loader.proxy.InjectPacket(chat, Direction.Outgoing);
            }
        }

        private string translate(string message, string from, string to)
        {
            if (message.StartsWith("/me "))
                message = message.Substring("/me ".Length);
            message = message.Trim();
            if (message.Length > 2)
            {
                from = this.GetLangAbbreviation(from);
                to = this.GetLangAbbreviation(to);

                if(from != to)
                {
                    try
                    {
                        // Create a request
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://translate.google.com/translate_t");

                        // Post data
                        request.Method = "POST";
                        request.ContentType = "application/x-www-form-urlencoded";
                        string postData = "&hl=en&ie=UTF8&text=" + message + "&langpair=" + from + "|" + to;
                        request.ContentLength = postData.Length;
                        StreamWriter writer = new StreamWriter(request.GetRequestStream());
                        writer.Write(postData);
                        writer.Close();

                        // Get result
                        WebResponse response = request.GetResponse();
                        StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
                        string result = reader.ReadToEnd();
                        reader.Close();
                        // find the result... don't you just love regular expressions? XD
                        Match match = Regex.Match(result, @"<div[^>]*?id\s*=\s*result_box[^>]*>(.*?)?</div>");
                        if (match.Success)
                        {
                            result = match.Groups[1].Value.Trim();
                            HtmlTextArea handleSpecials = new HtmlTextArea();
                            handleSpecials.InnerHtml = result;
                            result = handleSpecials.InnerText;
                            if (message != result)
                                return "/me (" + to + "): " + result;
                            else
                                Console.WriteLine("No translation for: " + message);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Translation Exception:"+ex.Message);
                    }
                }
            }
            return null;
        }
    }
}